use std::net::SocketAddr;

#[derive(Debug, PartialEq, Eq)]
pub enum PacketType {
    Unknown,
    Rtp,
    Rtcp,
    Stun,
}

pub const MAX_UDP_BUFFER_SIZE: usize = 1500;

pub struct Packet {
    pub remote_addr: SocketAddr,
    pub typ: PacketType,
    pub len: usize,
    pub buf: [u8; MAX_UDP_BUFFER_SIZE],
}

pub fn get_packet_type(data: &[u8]) -> PacketType {
    if data.len() <= 2 {
        return PacketType::Unknown;
    }
    if data[0] == 0 || data[0] == 1 {
        return PacketType::Stun;
    } else if data[0] >= 20 && data[0] <= 64 {
        return PacketType::Unknown;
    } else {
        let rtp_payload = data[1] & 0x7f;
        if rtp_payload < 64 || rtp_payload >= 96 {
            return PacketType::Rtp;
        } else if rtp_payload >= 64 && rtp_payload < 96 {
            return PacketType::Rtcp;
        } else {
            return PacketType::Unknown; /* maybe SCTP */
        }
    }
}

// Abort on drop

use futures::future::pending;
use std::mem;

use tokio::task::{JoinError, JoinHandle};
pub struct AbortOnDropHandle<T> {
    inner: JoinHandle<T>,
}

impl<T> Drop for AbortOnDropHandle<T> {
    fn drop(&mut self) {
        self.inner.abort();
    }
}

impl<T> From<JoinHandle<T>> for AbortOnDropHandle<T> {
    fn from(inner: JoinHandle<T>) -> Self {
        Self { inner }
    }
}
impl<T: Send + 'static> AbortOnDropHandle<T> {
    pub async fn join(mut self) -> Result<T, JoinError> {
        let handle: JoinHandle<T> = mem::replace(&mut self.inner, tokio::spawn(pending::<T>()));
        handle.await
    }
}
